/*
  Copyright (c) 2011, Mikheev Rostislav
  Copyright (c) 2011, FreshFarsh team

  Steel Engine source code is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/**
  @author Mikheev Rostislav <hacenator@gmail.com>
  @date 23.03.2011
  @brief Battle Ground map class header file
*/

#ifndef _H_STEEL_MAP
#define _H_STEEL_MAP

#include <stdlib.h>
#include <stdint.h>
#include <string>
#include <limits>
#include "gui/core.h"
#include "GL/glew.h"
#include "common.h"
#include "opengl_shorthands.h"
#include "exception.h"
#include "structures.h"
#include "math_ext.h"
#include "listener.h"
#include "io_file.h"
#include "window_manager.h"
#include "camera.h"

namespace _STEEL_NAMESPACE {

/// Curve data
struct Curves {
  int curves_count; ///< curves count
  Curve2* points; ///< curve points data
};

/// Vertex Buffer Object Structure
struct VBO {
  GLuint vertex_buffer; ///< vertex Buffer
  GLuint index_buffer; ///< indexes buffer
  GLuint texture; ///< texture buffer
  GLuint target; ///< target
};

/// Polygon Structure
struct Polygon {
  int vertex_count; ///< polygon vertex count
  Vertex2D* points; ///< polygon vertex data

  VBO vbo; ///< vertex buffer object from vertex data
};

class Map:
  public IMouseListener {
 public:
  Map(const WindowManager* viewport, const Camera* camera, const GUILayer* gui);
  virtual ~Map();

  void Draw();

  bool LoadFromFile(const char* filename); ///< loading map data from file
  bool SaveToFile(const char* filename); ///< saving map data to file

  void set_edit_mode(bool value) {
    _edit_mode = value;
    //TODO(hacenator) Map reloading required. Curves is empty
  }

  bool get_edit_mode() {
    return _edit_mode;
  }

 private:
  static const int _magick; ///< map file header magick number

  Camera* _camera; ///< game camera
  GUILayer* _gui; ///< game gui

  // viewport size
  WindowManager* _viewport;
  int _viewport_width; ///< viewport width
  int _viewport_height; ///< viewport height

  // map info
  wchar_t* _name; ///< map name
  wchar_t* _author_name; ///< map author name

  // edit mode
  bool _edit_mode; ///< draw map in edit/debug mode
  Point2f _edit_mouse; ///< editor mouse position

  Rect _map_borders; ///< map borders
  int _ground_count; ///< polygons count

  // map structures
  Polygon* _ground; ///< calculated maps polygons ready for rendering

  // TODO(hacenator) Curves is needed only in map editor mode
  // or on map loading stage. May be cleaned for end-players
  // after map is loaded.
  int _curved_polygons_count; ///<
  Curves* _curved_polygons; ///< map data in curved polygons

  // options
  // background
  GLuint _background_index_buffer; ///< background index data buffer identifier
  GLuint _background_vertex_buffer; ///< background vertex data buffer identifier
  Quad2D _background_data; ///< background vertex and color data

  // grid options
  GLuint _grid_index_buffer; ///< grid index data buffer identifier
  GLuint _grid_vertex_buffer; ///< grid vertex data buffer identifier
  RGBAColor _grid_color; ///< grid color data

  bool _draw_grid; ///< draw grid flag
  int _grid_frequency; ///< grid frequency
  int _grid_size; ///< grid size
  int _grid_zoom; ///< grid zoom //TODO(hacenator)

  void CreateBackground(); ///< Create background
  void CalculateEditorGrid(int viewport_width, int viewport_height); ///< Calculate editor grid
  bool CurvesToPoly(Curves* curves, Polygon* polygon); ///< convert all curves to polygons
  bool PolyPrepare(Polygon* poly); ///< prepare polygons to rendering

  void ClearEditorGrid(); ///< clear editor grid data
  void ClearCurvedPolygons(); ///< clear curved polygons data
  void ClearGroundData(); ///< clear calculated ground data

  int CurveDivision(Point2f* points);

  void DrawBackground(); ///< render map background
  void DrawGround(); ///< render map ground
  void DrawEditorGrid(); ///< render editor grid

  // IMouseListener classes
  void OnMouseMove(int x, int y);
  void OnMouseUp(int x, int y, int button);
  void OnMouseDown(int x, int y, int button);

  //
  void CalculateMapSize(); ///< calculate map borders
  // map optimization divizioning
};

}

#endif // _H_STEEL_MAP
